package com.softme.trade.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class ReflectUtil
{
	/**Ex: Nome do método setCurrentUser
	 * o Retorno será CurrentUser
	 * 
	 * @param method
	 * @return
	 */
	public static String getMethodNameWithoutGetAndSet(Method method)
	{
		String methodName = method.getName();
		methodName = methodName.replace("get", "").replace("set", "").replace("is", "");
		
		return methodName;
	}
	
	public static List<Method> getListMethodFrom(Object obj)
	{
		return getListMethodFrom(obj.getClass());
	}

	public static List<Method> getListMethodFrom(String nameClass) throws ClassNotFoundException
	{
		return getListMethodFrom(Class.forName(nameClass));
	}

	public static List<Method> getListMethodFrom(Class<?> clazz)
	{
		return getListMethodFrom(clazz, null);
	}

	public static List<Method> getListMethodFrom(Class<?> clazz, String startWith)
	{
		Method[] methods = clazz.getDeclaredMethods();
		List<Method> listMethods = new ArrayList<Method>();

		for (int i = 0; i < methods.length; i++)
		{
			if (startWith != null)
			{
				if (methods[i].getName().startsWith(startWith))
					listMethods.add(methods[i]);
			}
			else
				listMethods.add(methods[i]);
		}

		return listMethods;
	}
	
	public static Object invokeMethod(final String className, final String methodName)
	{
		try
		{
			return invokeMethod(Class.forName(className), methodName);
		}
		catch (ClassNotFoundException e)
		{
			e.printStackTrace();
			return null;
		}
	}

	public static Object invokeMethod(final Class<?> clazz, final String methodName)
	{
		return invokeMethod(clazz, methodName, new Object[0]);
	}
	
	public static Object invokeMethod(final Class<?> clazz, final String methodName, final Object params[])
	{
		return invokeMethod(clazz, methodName, params, getParameterTypes(params));
	}
	
	public static Object invokeMethod(final Class<?> clazz, final String methodName, final Object params[], final Class<?> paramsType[])
	{
		return invokeMethod(false, clazz, methodName, params, paramsType);
	}	
	
	public static Object invokeStaticMethod(final Class<?> clazz, final String methodName, final Object params[])
	{
		return invokeStaticMethod(clazz, methodName, params, getParameterTypes(params));
	}
	
	public static Object invokeStaticMethod(final Class<?> clazz, final String methodName, final Object params[], final Class<?> paramsType[])
	{
		return invokeMethod(true, clazz, methodName, params, paramsType);
	}
	
	private static Object invokeMethod(final boolean isStatic, final Class<?> clazz, final String methodName, final Object params[], final Class<?> paramsType[])
	{
		Object result = null;
		try
		{
			Method method= clazz.getMethod(methodName, paramsType);
			
			Object o = null;
			
			if(!isStatic)
				o = clazz.newInstance();
			
			result = method.invoke(o, params);
		}
		catch (InstantiationException e)
		{
			e.printStackTrace();
		}
		catch (IllegalAccessException e)
		{
			e.printStackTrace();
		}
		catch (SecurityException e)
		{
			e.printStackTrace();
		}
		catch (NoSuchMethodException e)
		{
			e.printStackTrace();
		}
		catch (IllegalArgumentException e)
		{
			e.printStackTrace();
		}
		catch (InvocationTargetException e)
		{
			e.printStackTrace();
		}
		return result;
	}
	
	private static Class<?>[] getParameterTypes(Object[] params)
	{
		Class<?> clazz[] = new Class<?>[params.length];
		for(int x = 0; x < params.length; x++)
		{
			clazz[x] = params[x].getClass();
		}
		return clazz;
	}
	
}
